#include<stdio.h>
#include<signal.h>
#include<pthread.h>
#include<stdlib.h>
#include<time.h>
#include<gmp.h>


  unsigned long inteirob0;
  double doublea0 = 0.25;
  unsigned long bitsdeprecisao;
  int i = 0;
  int fimprog = 0;
  time_t inicio,fim;

int main(){

  inicio = time(NULL);
  mpf_set_default_prec(33219280);//precisao necessaria para alcanca dez milhoes de digitos
  
  mpf_t an;// variavel An de gauss
  mpf_t ann;//variavel An + 1
  mpf_t tn;//o mesmo vale para as variaveies seguintes
  mpf_t tnn;
  mpf_t pn;
  mpf_t pnn;
  mpf_t bn;
  mpf_t bnn;//logo abaixo variaveis que auxliares durante a aritmetica
  mpf_t temp,temp2,temp3,
  temp4,temp5,temp6,temp7,temp8;
  mpf_t pi;
  mpf_init(an);//todo tipo multiprecision precisa ser inicializado, se nao ocorre erro ao tentar usar a variavel nao inicializa com essas funcoes
  mpf_init(ann);
  mpf_init(tn);
  mpf_init(tnn);
  mpf_init(pn);
  mpf_init(pnn);
  mpf_init(bn);
  mpf_init(bnn);
  mpf_init(pi);
  mpf_init(temp);
  mpf_init(temp2);
  mpf_init(temp3);
  mpf_init(temp4);
  mpf_init(temp5);
  mpf_init(temp6);
  mpf_init(temp7);
  mpf_init(temp8);

  bitsdeprecisao = mpf_get_default_prec();//apenas confere a precisao
  printf("Essa eh a precisao default %ld \n",bitsdeprecisao);   
  inteirob0 = 2;//inicializa as variaveis para as iteracies
  mpf_set_si(bn, inteirob0);
  mpf_sqrt(bn,bn);
  mpf_div_ui(bn,bn,inteirob0); 
  mpf_set_ui(an,1);
  mpf_set_d(tn,0.25);
  mpf_set_ui(pn,1);

  for (i = 0; i < 23; i++){

    mpf_add(temp,an,bn);//praticamente todo o algoritmo de gauss nesse for
    mpf_div_ui(temp,temp,2);
    mpf_set( ann, temp );
    mpf_mul(temp2,an,bn);
    mpf_sqrt(bnn,temp2);
    mpf_sub(temp3,an,ann);
    mpf_pow_ui(temp4,temp3,2);
    mpf_mul(temp5,temp4,pn);
    mpf_sub(tnn,tn,temp5);
    mpf_mul_ui(pnn,pn,2);

    mpf_add(temp6, ann, bnn);//printando o valor de pi
    mpf_pow_ui(temp7, temp6, 2);
    mpf_mul_ui(temp8,tnn,4);
    mpf_div(pi,temp7,temp8);
    printf("\niteracao %d",i+1);
    gmp_printf("\nEsse eh o valor de pi %.10000000Ff\n",pi);
    
    mpf_set(an,ann);//setando os valores para a proxima itecacao,
    mpf_set(bn,bnn);
    mpf_set(tn,tnn);
    mpf_set(pn,pnn);
    
  }
 
    mpf_add(temp6, ann, bnn);//imprimindo pi por causa da ultima itecao que imprime  o valor da penultima
    mpf_pow_ui(temp7, temp6, 2);
    mpf_mul_ui(temp8,tnn,4);
    mpf_div(pi,temp7,temp8);
    printf("\niteracao %d",i+1);
    gmp_printf("\nEsse eh o valor de pi %.10000000Ff\n",pi); 
 /* limpando a memoria para nao influenciar nas proximas execucoes*/
 mpf_clear(an);
 mpf_clear(ann);
 mpf_clear(bn);
 mpf_clear(bnn);
 mpf_clear(tn);
 mpf_clear(tnn);
 mpf_clear(pn);
 mpf_clear(pnn);
 mpf_clear(pi);
 mpf_clear(temp);
 mpf_clear(temp2);
 mpf_clear(temp3);
 mpf_clear(temp4);
 mpf_clear(temp5);
 mpf_clear(temp6);
 mpf_clear(temp7);
 mpf_clear(temp8);
 
 fim = time(NULL);//calculando o tempo, para isso eh marcado o tempo de inicio e fim e eh usada a funcao abaixo - difftime
 printf("\nprograma foi completo com exito, e o tempo de execucao foi de:\n%.0f segundos\n",difftime(fim,inicio));
return 0;
}
